home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Speccy ClassiX 1998
/
Speccy ClassiX 98.iso
/
amiga_system
/
the_aminet
/
dev
/
gcc
/
ixemulsrc.lha
/
ixemul-41.4
/
library
/
open.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-10-02
|
8KB
|
264 lines
/*
* This file is part of ixemul.library for the Amiga.
* Copyright (C) 1991, 1992 Markus M. Wild
* Portions Copyright (C) 1994 Rafael W. Luebbert
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: open.c,v 1.4 1994/06/19 15:14:07 rluebbert Exp $
*
* $Log: open.c,v $
* Revision 1.4 1994/06/19 15:14:07 rluebbert
* *** empty log message ***
*
* Revision 1.2 1992/07/28 00:32:04 mwild
* pass convert_dir the original signal mask, to check for pending signals
*
* Revision 1.1 1992/05/14 19:55:40 mwild
* Initial revision
*
*/
#define KERNEL
#include "ixemul.h"
#include "kprintf.h"
/* standard functions.. could get overridden in a network environment */
extern int __ioctl (), __fselect (), __close ();
/* "normal" functions, means do half-async writes & sync reads */
extern int __write (), __read ();
/* sync-write, waits for completion of write, this gets enabled by
* O_FSYNC */
extern int __sync_write ();
extern void __fasync_handler ();
/* incore functions */
extern int __mread (), __mclose ();
extern int __ioerr_to_errno ();
int
open (char *name, int mode, int perms)
{
int fd;
struct file *f;
BPTR fh;
int len, late_stat;
int omask, error = 0;
int amode, fnofs;
if (name == NULL) /* sanity check */
return EACCES;
mode = FFLAGS(mode);
KPRINTF (("open1: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
/* inhibit signals */
omask = syscall (SYS_sigsetmask, ~0);
errno = falloc (&f, &fd);
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
if (errno != 0)
{
syscall (SYS_sigsetmask, omask);
return -1;
}
/* we now got the file, ie. since its count is > 0, no other process
* will get it with falloc() */
KPRINTF (("open2: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
KPRINTF (("open3: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
/* init those fields */
f->f_stb_dirty = 0;
late_stat = 0;
if (syscall (SYS_stat, name, &f->f_stb) < 0)
{
/* there can mainly be two reasons for stat() to fail. Either the
* file really doesn't exist (ENOENT), or then the filesystem/handler
* doesn't support file locks. */
/* if we should get out of here without an error, init the stat
* buffer after having opened the file with __fstat, this sets some
* reasonable parameters (see end of function). */
late_stat = 1;
if ((errno == ENOENT) && (mode & O_CREAT))
{
/* can't set permissions on an open file, so this has to be done
* by 'close' */
f->f_stb.st_mode = perms;
f->f_stb_dirty = 1;
}
}
f->f_flags = mode & FMASK;
KPRINTF (("open4: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
/* initialise the packet. The only thing needed at this time is its
* header, filling in of port, action & args will be done when it's
* used */
__init_std_packet (&f->f_sp);
/* ok, so lets try to open the file... */
/* do this *only* if the stat() above was successful !! */
if (!late_stat && S_ISDIR (f->f_stb.st_mode) && !(mode & FWRITE))
{
if (convert_dir (f, name, omask) == 0)
goto ret_ok;
else
goto error;
}
KPRINTF (("open5: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
/* filter invalid modes */
switch (mode & (O_CREAT|O_TRUNC|O_EXCL))
{
case O_EXCL:
case O_EXCL|O_TRUNC:
/* can never succeed ! */
error = EINVAL;
goto error;
case O_CREAT|O_EXCL:
case O_CREAT|O_EXCL|O_TRUNC:
if (! late_stat)
{
error = EEXIST;
goto error;
}
break;
}
amode = (mode & O_CREAT) ? MODE_READWRITE : MODE_OLDFILE;
do
{
if (!strcmp(name, "*") || !strcasecmp(name, "console:"))
/* Temporary patch for KingCON 1.3, which seems to have problems with
ACTION_FINDINPUT of "*"/"console:" when "dp_Port" of the packet is
not set to sender's "pr_MsgPort" - that's what IXEmul makes on
clients' startup during initialization of "stderr". */
fh=Open(name, amode);
else
fh = __open (name, amode);
if (! fh)
{
int err = IoErr();
/* For those handlers that do not understand MODE_READWRITE (e.g. PAR: ) */
if (err == ERROR_ACTION_NOT_KNOWN && amode == MODE_READWRITE)
{
amode = MODE_NEWFILE;
}
else
{
error = __ioerr_to_errno (err);
goto error;
}
}
} while (!fh);
/* now.. we're lucky, we actually opened the file! */
f->f_fh = (struct FileHandle *) BTOCPTR(fh);
if (mode & FWRITE)
f->f_write = (mode & O_FSYNC) ? __sync_write : __write;
if (mode & FREAD)
f->f_read = __read;
#if 0
/* won't work that way, I'll think something up later.. */
/* in this case, we have to setup a handler that is called when ever
* something arrives at the rw-port, and then walk our filetable and
* decide whether the packet belonged to a file that has FASYNC set */
if (mode & FASYNC) signal (__rwport->mp_SigBit, __fasync_handler);
#endif
f->f_ioctl = __ioctl;
f->f_select = __fselect;
f->f_close = __close;
f->f_type = DTYPE_FILE;
ret_ok:
/*
* have to use kmalloc() instead of malloc(), because this is no task-private
* data, it could (in the future) be shared by other tasks
*/
f->f_name = (void *) kmalloc (strlen (name) + 1);
strcpy (f->f_name, name);
/* ok, we're almost done. If desired, init the stat buffer to the
* information we can get from an open file descriptor */
if (late_stat) __fstat (f);
/* if the file qualifies, try to change it into a DTYPE_MEM file */
if (!late_stat && f->f_type == DTYPE_FILE
&& f->f_stb.st_size < ix.ix_membuf_limit && mode == FREAD)
{
void *buf;
KPRINTF (("open6: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
/* try to obtain the needed memory */
buf = (void *) kmalloc (f->f_stb.st_size);
if (buf)
if (syscall (SYS_read, fd, buf, f->f_stb.st_size) == f->f_stb.st_size)
{
KPRINTF (("open7: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
__Close (CTOBPTR (f->f_fh));
KPRINTF (("open8: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
f->f_type = DTYPE_MEM;
f->f_mf.mf_offset = 0;
f->f_mf.mf_buffer = buf;
f->f_read = __mread;
f->f_close = __mclose;
f->f_ioctl = 0;
f->f_select = 0;
}
else
kfree (buf);
}
syscall (SYS_sigsetmask, omask);
if (error)
{
errno = error;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
}
if (!error && (mode & O_TRUNC) && (amode != MODE_NEWFILE))
syscall(SYS_ftruncate, fd, 0);
/* return the descriptor */
return fd;
error:
/* free the file */
u.u_ofile[fd] = 0;
f->f_count--;
syscall (SYS_sigsetmask, omask);
errno = error;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return -1;
}